/*********************************************************************************************************
*
* File                : main.c
* Hardware Environment: 
* Build Environment   : RealView MDK-ARM  Version: 4.20
* Version             : V1.0
* By                  : 
*
*                                  (c) Copyright 2005-2011, WaveShare
*                                       http://www.waveshare.net
*                                          All Rights Reserved
*
*********************************************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"
//extern u32 DemuraAddHL;


#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
    #pragma data_alignment=4   
  #endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
   
__ALIGN_BEGIN USB_OTG_CORE_HANDLE    USB_OTG_dev __ALIGN_END ;
/**
* @}
*/ 

u8(*pf)(char*,u32);

FRESULT res = FR_NOT_READY;
FATFS USB_fatfs,SD_fatfs,NAND_fatfs;
FIL usb_file,sd_file,sd_file1,NAND_file,NAND_file1;


u8  disk = NO_Disc;

u8  Err_code = None_Err;                                    //错误 代码        
u8  CFG_Valid_flag = 0;                                     //更新时 CFG文件 有效标志



u32 Length = 0;
u32 Delay_time = 0;
u32 Count_time = 0;
u8  FSMC_Send_Flag = 0;
u8  Loaded_BMPNum = 0;                                     //已经载入的BMP图片数量
char valid_FileNames [File_NUM_MAX][File_NAME_MAX];      //SD卡有效分辨率的BMP图片名称
u8  Key_vaild = 1,Key_Auto = 0;
u16 LED_Flick=0;
u32 Pure_Color_Table[8]={WHITE,RED,GREEN,BLUE,YELLOW,PINK,CYAN,BLACK};
u8  DDR_Addr_ID=0;
void Generate_cfg(USB_OTG_CORE_HANDLE *pdev,u32 Address)
{
        u16 temp,temp1;
		j=0;
        
		FLASH_If_Read(&Address, buffer1, 0,2048);	//将FLASH的模组Timing数据读取出来，准备发送给FPGA

		for(i=0;i<16;i++)
		{
				buffer[i*4] = 		(u8)(buffer1[i]>>24);
				buffer[(i*4)+1] = (u8)(buffer1[i]>>16);
				buffer[(i*4)+2] = (u8)(buffer1[i]>>8);
				buffer[(i*4)+3] = (u8)(buffer1[i]);
		}

		if((buffer[Timing_Data_Max-1] >= 0xA0))		//Mipi的配置 读取,并且确保FLAHS里面有SSD2828的配置代码
		{
			while(buffer1[16+j] != 0xffffffff)
			{
					buffer[Timing_Data_Max + (j*3)] 			= (u8)(buffer1[16+j]>>16);
					buffer[Timing_Data_Max + (j*3) + 1] 	= (u8)(buffer1[16+j]>>8);
					buffer[Timing_Data_Max + (j*3)	+	2]  = (u8)(buffer1[16+j]);
					j++;
			}
			temp = Timing_Data_Max + (j*3);
			temp1 = 16+j+1;
			buffer[temp] = 0xff;
			j = 0;
			while(buffer1[temp1+j] != 0xffffffff)
			{
					buffer[temp+j+1] = (u8)(buffer1[temp1+j]);
					j++;
			}
			buffer[temp+j+1] = 0xff;
            File_length = temp+j+2;	
		}
        else if(buffer[Timing_Data_Max-1] == 0x55)      //RGB 或者SPI接口
        {
            temp = Timing_Data_Max;
            temp1 = 16;
            j = 0;
            while(buffer1[temp1+j] != 0xffffffff)
			{
					buffer[temp+j] = (u8)(buffer1[temp1+j]);
					j++;
			}
            buffer[temp+j] = 0xff;
            File_length = temp+j+1;	
        }
			
		//************将FLash内的数据写到PC，生成文件********************
		//***************************************************************

		STM2PC_FilConfig(pdev,CDC_IN_EP,USB_Rx_Buffer[0],Uart_rx_flag,buffer,File_length,Uart_Error_None);
		//****************************************************************
}



u8 Updata_cfg(char* cfg_name,u32 Address)
{	
	u8 error_time=0;
	res = f_open(&sd_file,	cfg_name,FA_OPEN_EXISTING|FA_READ);	//打开 U盘配置文件
      
	if(res == FR_OK)		//里面有配置文件，需要将配置文件拷贝到芯片FLASH
	{	
        res = f_read(&sd_file,buffer, Timing_Data_Max,&br);//读数据，（文件指针，数据存放指针，需要读取的量，正确读出的量）
        if(((buffer[0] == 0x47)&&(buffer[1] == 0x56)&&(buffer[2] == 0x4f)&&(buffer[3] == 0x43)&&(buffer[4] == 0x6F)&&(buffer[5] == 0x6E))||(CFG_Valid_flag == 1))//文件初始对应的是"GVOConfig.cfg"
        {
            FLASH_Unlock();		//芯片内部FLASH每次操作都需要解锁
            FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); 
            while((FLASH_EraseSector(Inter_Flash_Sect, VoltageRange_3) != FLASH_COMPLETE)&&(error_time<10))	//每次写入FLASH之前需要清除，清除是一个扇区一个扇区
                error_time++;
            if(error_time<10)
            {
                CFG_Valid_flag = 1;
                OLED.SigMode = buffer[Timing_Data_Max-15-1] & 0xf0;
        
                for(i = 0;i<(Timing_Data_Max/4);i++)	//将文件标识和Timing数据转换。byte的长度是64  因为FLASH存储是字存储，需要将byte转换成4个byte的字
                {
                    Timing_and_InitCode[i] = ((uint32_t)buffer[i*4]<<24)+((uint32_t)buffer[(i*4)+1]<<16)+((uint32_t)buffer[(i*4)+2]<<8)+((uint32_t)buffer[(i*4)+3]);
                }
                
                if (FLASH_If_Write(&Address, Timing_and_InitCode, Timing_Data_Max/4) != 0)	//写FLASH数据(地址指针，数据指针，写入个数)
                {
                    return 4;		//写FLASH出现错误
                }							
                f_lseek(&sd_file,Timing_Data_Max);
                res = f_read(&sd_file,buffer,512,&br);//读数据，（文件指针，数据存放指针，需要读取的量，正确读出的量）

                if((OLED.SigMode == Mipi_Mode)||(OLED.SigMode == CMD_Mode))
                {
                    for (i = 0; i < 512; i++)		//将2828的配置数据 转换成字
                    {
                        if (buffer[i * 3] == 0xff)
                        {
                                Length++;
                                break;                    
                        }
                        //    0x H H H H  :   31:24->00(没作用)   23:16->寄存器地址    15:0->寄存器值(高位在前)
                        SSD28xx_Code[SSD28xxCode_count] = ((uint32_t)buffer[i * 3]<<16) + ((uint32_t)buffer[i * 3 + 1]<<8) + ((uint32_t)buffer[i * 3 + 2]);
                        Length += 3;
                        SSD28xxCode_count ++;																						
                    }
                    SSD28xx_Code[i]=0xffffffff;		        //该数据区分SSD2828配置代码和 DriverIC初始化代码									
                    if (FLASH_If_Write(&Address, SSD28xx_Code, i+1) != 0)	//写2828配置写入到FLASH
                    {
                            return 4;		//写FLASH出现错误
                    }			
                }																				
                f_lseek(&sd_file,Timing_Data_Max+Length);
                if(1)	//死循环，一直朝FLASH搬数据，知道数据搬完跳出死循环
                {		
                    res = f_read(&sd_file,buffer,4096,&br);//读数据，（文件指针，数据存放指针，需要读取的量，正确读出的量）
                   // if(res||br == 0)	//br为0说明，文件已经被读完了，没有数据可读了，那么就跳出
                   // break;
                    
                    for (i = 0; i < 4096; i += (Code_length+1))
                    {
                            Code_length = buffer[i];	//每一句初始化代码的 数据长度

                            if (Code_length == 0xff)	//判断长度有255说明 ，到初始化代码的最后
                            {
                                    break;
                            }
                            Timing_and_InitCode[0] =	Code_length;	//数组中的[0]：这一句初始化代码的数据长度									
                            for (j = 1; j < Code_length+1; j++)	//递增将 初始化代码写入到数组
                            {											
                                    Timing_and_InitCode[j] = ((uint32_t)buffer[i+j]);
                            }									
                            if (FLASH_If_Write(&Address, Timing_and_InitCode, Code_length+1) != 0)	//写这一句初始化代码写入到FLASH
                            {
                                    return 4;		//写FLASH出现错误
                            }	
                            
                            InitCode_count ++;	//即将写下一个数组(下一句初始化代码)																											
                    }	
                    Timing_and_InitCode[0]=0xffffffff;
                    if (FLASH_If_Write(&Address, Timing_and_InitCode, 1) != 0)	//写这一句初始化代码写入到FLASH
                    { 
                            return 4;		//写FLASH出现错误
                    }				
                }                    
			}	
			else
			{
				return 2;
			}						
		}
        else
        {            
            return 3;
        }
		FLASH_Lock();		//FLASH操作结束，锁上	
    }
	else
	{
        for(i=0;i<100;i++)      //让红灯 连续闪烁100次
        {
            LED2_HIGH;
            delay_ms(50);
            LED2_LOW;
            delay_ms(50);
        }
		return 1;
	}
	f_close(&sd_file);	//关闭文件指针
    return 0;
}



void Updata_cfg_printf(u8(*pf)(char*,u32),char* cfg_name,u32 Address)
{
	switch(pf(cfg_name,Address))
	{
		case 0 : printf (" PGConfig%d 更新成功!\r\n",cfg_name[11]-48);   break;
		case 1 : printf (" PGConfig%d 更新失败!\t打开文件异常\r\n",cfg_name[11]-48);   break;
		case 2 : printf (" PGConfig%d 更新失败!\t擦除FLASH异常\r\n",cfg_name[11]-48);   break;
		case 3 : printf (" PGConfig%d 更新失败!\t配置文件异常\r\n",cfg_name[11]-48);   break;
		case 4 : printf (" PGConfig%d 更新失败!\t写入FLASH异常\r\n",cfg_name[11]-48);   break;
		default: printf (" PGConfig%d 更新失败!\t其他异常\r\n",cfg_name[11]-48);   break;
	}
    SSD28xxCode_count = 0;
    InitCode_count = 0;
}


void Panel_ON(u8 signal_mode,u32* buf)			//??FLASH?????4??Mipi???
{
	u16 SSD_ID = 0;     //SSD2828?????ID
	i = 16;			//SSD2828?????? ???FLASH?????? 16?????'	
	if((signal_mode == Mipi_Mode)||(signal_mode == CMD_Mode))
	{
		while(SSD_ID!=0x2828)
		{
				SSD_ID = SSD2828_R_Reg(OLED.SigMode,CS1_2,0xB0);	
		}	    		
		while(buf[i] != 0xFFFFFFFF)		//??SSD2828??????????????2828
		{
			SSD28xx_Code[0] = buf[i];
			i++;
			if((SSD28xx_Code[0]&0x00ff0001)!=0x00b70001) //send the 2828cfg reg ,if not inter mipi hs mode, 
			{	
				SSD2828_W_Reg(signal_mode,CS1_2,(u8)(SSD28xx_Code[0]>>16),(u16)SSD28xx_Code[0]);
			}
		}
		delay_ms(20);
		i++;		//SSD2828?????? ???FLASH?????? xxx+2?????'
	}
	while(buf[i] != 0xFFFFFFFF) //initial code 
	{
		InitCode_valid[0][0] = (u8)buf[i];		//????j?h???? ??????
		for(j=1;j<buf[i]+1;j++)												
			InitCode_valid[0][j] = (u8)buf[i+j];
		i += (buf[i]+1);
		if((OLED.SigMode == Mipi_Mode)||(OLED.SigMode == CMD_Mode))		
		{		
				SSD2828_W_Array(signal_mode,CS1_2,InitCode_valid[0],0);
				if(InitCode_valid[0][1]==0x11)
				{
					FSMC_Pure_colour(WHITE); 
					Load_done_HIGH;
					delay_ms(100);
				}
		}
		else if((OLED.SigMode == SPI3_Mode)||(OLED.SigMode == SPI4_Mode))
		{
				SPI_Write_u8_Array(signal_mode,CS1_2,(u8 *)InitCode_valid[0]);
		}
	}
	if((OLED.SigMode == Mipi_Mode)||(OLED.SigMode == CMD_Mode))		
	{
		SSD2828_W_Reg(signal_mode,CS1_2,(u8)(SSD28xx_Code[0]>>16),(u16)SSD28xx_Code[0]);//inter hs mode
		delay_ms(5);
		SSD2828_W_Array(signal_mode,CS1_2,InitCode_valid[0],0); //R66455
	}
	else if((OLED.SigMode == SPI3_Mode)||(OLED.SigMode == SPI4_Mode))
	{
		SPI_Write_u8_Cmd(OLED.SigMode,CS1_2,0x11);
		delay_ms(120);
		SPI_Write_u8_Cmd(OLED.SigMode,CS1_2,0x29);
		delay_ms(20);  
	}
}
/*
void Trim_Initial_Data(u8 signal_mode,u32* buf)			//?????FLASH?????4??Mipi???

{
	i = 16;			//SSD2828?????? ???FLASH?????? 16?????'	
	if((signal_mode == Mipi_Mode)||(signal_mode == CMD_Mode))
	{
		while(buf[i] != 0xFFFFFFFF)		//??SSD2828???????? ????????????
		{
			SSD28xx_Code[SSD28xxCode_count] = buf[i];
			i++;
			SSD28xxCode_count ++;		//????? SSD2828???? ??? ???

		}
		i++;		//SSD2828?????? ???FLASH?????? xxx+2?????'
	}
	while(buf[i] != 0xFFFFFFFF)
	{
		InitCode_valid[InitCode_count][0] = (u8)buf[i];		//????j?h???? ??????

		for(j=1;j<buf[i]+1;j++)												
			InitCode_valid[InitCode_count][j] = (u8)buf[i+j];
		i += (buf[i]+1);
		InitCode_count ++;	//???????h??????(??h???'??????)	
	}
}
*/

/********************************************
功能： 将NandFlash或者SD卡里面的所有图片 判断是否为当前分辨率图片
参数1：Disc：磁盘标志  Nand_Disc/All_Disc
参数2：H_Size：水平分辨率
参数3：V_Size：垂直分辨率
返回： 符合当前分辨率的图片数量
*********************************************/
u8 BMP_Name_Process(u8 Disc,u16 H_Size,u16 V_Size)		//图片分辨率 处理，整理出和配置文件的分辨率相对应的 BMP图片
{
	u16 BMP_HP,BMP_VP;                                          //BMP图片的 水平和垂直分辨率
    u8 Current_BMP = 0;         //图片名称 处理时的 变量
	u8 Num = 0;
	if(PicCnt > 0)
	{
		for(;;)
		{
            if(Disc == Nand_Disc)
            {
                fout = fopen (FileNames[Current_BMP],"r");        //以只读的方式 打开 Nandflash 里的配置文件 
                if(fout != NULL)
                  res = FR_OK ; 
            }
            else if(Disc == All_Disc)
                res = f_open(&sd_file,	FileNames[Current_BMP],FA_OPEN_EXISTING|FA_READ);	//打开 U盘中的BMP图片
			if(res == FR_OK)	
			{   
                if(Disc == Nand_Disc)
                    br = fread(buffer,sizeof(uint8_t), 54, fout);
                else if(Disc == All_Disc)
					res=f_read(&sd_file,buffer,54,&br);		//读取BMP图片的前面54个数据，里面包含了BMP图片的一些参数
																								// 18,19,20,21是BMP图片的水平大小
																								// 22,23,24,25是BMP图片的垂直大小
																								// 28,29 是BMP的颜色深度  (29<<8)+28=32,表示颜色深度是32位
                BMP_HP = (buffer[19]<<8)+(buffer[18]);	//BMP图片水平大小
                BMP_VP = (buffer[23]<<8)+(buffer[22]);	//BMP图片垂直大小
                
                //判断该BMP图片的尺寸是否和当前配置文件的模组尺寸大小一致
                if((BMP_VP == V_Size)&&(BMP_HP==H_Size))
                {	
                    memcpy(valid_FileNames[Num],FileNames[Current_BMP],File_NAME_MAX);
                    Num ++;
                    printf(" %s\r\n",FileNames[Current_BMP]);
                }
                if((Current_BMP+1) < PicCnt)
                        Current_BMP ++ ;
                else
                {
                    Current_BMP = 0;
                    break;
                }							
			}
            if(Disc == Nand_Disc)
                fclose(fout);	//关闭文件指针
            else if(Disc == All_Disc)
                f_close(&sd_file);	//关闭文件指针
		}
	}
    return Num;
}
/********************************************
功能： 通过FSMC发送DDR3存数数据的首地址
参数1：BMP_Addr_ID：首地址
返回： 无
*********************************************/
void FSMC_DDR_Addr(u8 BMP_Addr_ID)
{	
    //将即将发送的BMP存放的DDR3地址发送出去  
    write_cmd(0x3456);	
    write_cmd((u16)(((BMP_Addr_ID*OLED.V_pixel*OLED.H_pixel)*8/5)>>16));	
    write_cmd((u16)((BMP_Addr_ID*OLED.V_pixel*OLED.H_pixel)*8/5));	  
    write_cmd(0x6543); 
}
/********************************************
功能： 通过FSMC将NandFLash中的图片数据发送到FPGA
参数1：valid_BMP_Count：图片序号
返回： 0：成功   1：失败
*********************************************/
u8 FSMC_BMP_Data(float pclk,u8 valid_BMP_Count)
{							
    fout = fopen (FileNames[valid_BMP_Count],"r");        //以只读的方式 打开 Nandflash 里的配置文件 
    if(fout != NULL)
        res = FR_OK ;  
    if(res == FR_OK)
    {	
        j=1;
        fseek (fout, 54L, SEEK_SET);                       
        for(;;)
        {                
#if BMP_GROWTH == 1 
            if(OLED.H_pixel % 4 != 0)
                fseek (fout, ((OLED.V_pixel)-j)*(OLED.H_pixel*3+(OLED.H_pixel % 4))+54, SEEK_SET);  
            else
                fseek (fout, ((OLED.V_pixel)-j)*OLED.H_pixel*3+54, SEEK_SET); 
#else
            if(OLED.H_pixel % 4 != 0)
                fseek (fout, j*(OLED.H_pixel*3+(OLED.H_pixel % 4))+54, SEEK_SET);  
            else
                fseek (fout, j*OLED.H_pixel*3+54, SEEK_SET);                 
#endif                                                  		
            if(OLED.DisMode == 1)
            {
                br = fread(buffer1,sizeof(uint32_t), OLED.H_pixel*3/4, fout); 
                if(br == 0)
                    break; 

                for(i=0;i<OLED.H_pixel/8;i++)     //左右半屏 点亮屏幕
                {                                                              
                    Write_DATA(buffer1[i*3]&0x0000FFFF);
                    Write_DATA(((buffer1[i*3]>>16)&0x000000FF)  + ((buffer1[i*3+(OLED.H_pixel/8)*3]&0x000000FF)<<8));                     
                    Write_DATA(((buffer1[i*3+(OLED.H_pixel/8)*3]&0x00FFFF00)>>8));
                    
                    Write_DATA(((buffer1[i*3]>>24)&0x000000FF)  + ((buffer1[1+i*3]&0x000000FF)<<8));
                    Write_DATA(((buffer1[1+i*3]>>8)&0x000000FF)  + ((buffer1[i*3+(OLED.H_pixel/8)*3]&0xFF000000)>>16)); 
                    Write_DATA(buffer1[1+i*3+(OLED.H_pixel/8)*3]&0x0000FFFF); 
                    
                    Write_DATA((buffer1[1+i*3]&0xFFFF0000)>>16);
                    Write_DATA(((buffer1[2+i*3])&0x000000FF)  + ((buffer1[1+i*3+(OLED.H_pixel/8)*3]&0x00FF0000)>>8));
                    Write_DATA((((buffer1[1+i*3+(OLED.H_pixel/8)*3])&0xFF000000)>>24)  + ((buffer1[2+i*3+(OLED.H_pixel/8)*3]&0x000000FF)<<8));
                    
                    Write_DATA(((buffer1[2+i*3]&0x00FFFF00)>>8));
                    Write_DATA(((buffer1[2+i*3]&0xFF000000)>>24)  + (buffer1[2+i*3+(OLED.H_pixel/8)*3]&0x0000FF00)); 
                    Write_DATA((buffer1[2+i*3+(OLED.H_pixel/8)*3]&0xFFFF0000)>>16);                         
                }  
            }		
            else if(OLED.DisMode == 0)
            {
                br = fread(buffer1,sizeof(uint32_t), (OLED.H_pixel*3+(OLED.H_pixel % 4))/4, fout); 
                if(br == 0)
                    break; 
                for(i = 0;i<(br);i++)
                {
                    Write_DATA((u16)buffer1[i]); 
                    delay_6ns((pclk < 50) ? 50 : 0);
                    if(i == (br-1))
                    {
                        if((OLED.H_pixel % 4) == 0)
                        {
                            Write_DATA((u16)(buffer1[i]>>16));
                            delay_6ns((pclk < 50) ? 50 : 0);
                        }      
                    }   
                    else
                    {
                        Write_DATA((u16)(buffer1[i]>>16));
                        delay_6ns((pclk < 50) ? 50 : 0);
                    }
                }
            }
//#if BMP_GROWTH == 1                 
            j++;
            if(j == OLED.V_pixel+1)
                break;
//#endif                
        }
        fclose(fout);	//关闭文件指针
    }
    else
    {
        fclose(fout);	//关闭文件指针
        return 1;
    }			   
    return 0;
}

void FSMC_Send_BMP(float pclk,u8 DDR_Add_ID,u8 valid_BMP_Count)
{
	FSMC_DDR_Addr(DDR_Add_ID);
	FSMC_BMP_Data(pclk,valid_BMP_Count);
	FSMC_BMP_NUM (DDR_Add_ID); //当前画面序号

}

u8 BMP_Copy2_Nand(void)
{	
    u8 valid_BMP_Count = 0;
    if(Loaded_BMPNum!=0)	
        scan_files(disk,0);
    while((valid_BMP_Count != Loaded_BMPNum)&&(Loaded_BMPNum!=0))		//首先SD卡里面 有BMP图片
    {	
        memcpy(FileNames[valid_BMP_Count],valid_FileNames[valid_BMP_Count],File_NAME_MAX);
        res = f_open(&sd_file,	valid_FileNames[valid_BMP_Count],FA_OPEN_EXISTING|FA_READ);	//打开 U盘中的BMP图片                
        if(res == FR_OK)
        {		 
            fout = fopen (valid_FileNames[valid_BMP_Count],"w");       //创建NANDFLASH图片
            if(fout == NULL)
            {
            	printf (" 拷贝图片 失败!\t新建文件异常\r\n");
                return 2;
            }

            res = f_read(&sd_file,buffer,54,&br);
            bw = fwrite (buffer,sizeof(uint8_t), br, fout);                                                               

            f_lseek(&sd_file,54);             
            for(;;)
            {
                res = f_read(&sd_file,buffer,BMP_R_Byte_Max,&br);                
                if((res != FR_OK)||(br == 0))
                    break;                
                bw = fwrite (buffer,sizeof(uint8_t), br, fout);
                if(bw != br)
                {
                	printf (" 拷贝图片 失败!\t写入文件异常\r\n");
                    NAND_EraseChip();  
                    return 3;
                }
            }
            valid_BMP_Count++;
            fclose(fout);	//关闭文件指针
            f_close(&sd_file);	//关闭文件指针 
        }
        else
        {
            f_close(&sd_file);	//关闭文件指针
            printf (" 拷贝图片 失败!\t打开文件异常\r\n");
            return 1;	
        }
        printf(" 拷贝画面%s\r\n",valid_FileNames[valid_BMP_Count-1]);
    }
	printf (" 拷贝图片 成功!\r\n");   
   	printf(" 用时：%d\r\n",Delay_time);
    return 0;
}
OLED_Para OLED_Para_Process(u32* buf)
{
    OLED_Para Para;
	Para.DisMode = (((u8)(buf[12]>>24)&0x0f) < 2) ? 0 : 1;
	Para.H_pixel = (!Para.DisMode) ? (buf[8]>>24)+((buf[8]>>8)&0xff00) :2*((buf[8]>>24)+((buf[8]>>8)&0xff00));
	Para.V_pixel = (u16)(((buf[8]>>8)&0x00FF)+(buf[8]<<8));
	Para.pixel_clk = (float)((((buf[12]>>16)&0x00ff)|((buf[12]&0xff00)))/10.0);
	Para.SigMode = (u8)(buf[12]>>24)&0XF0;		//当前的 模组 信号格式		 //0x0n：MCU  0x1n：MIPI  0x2n：SPI3 0x3n：SPI4
	//Trim_Initial_Data(Para.SigMode,buf);		//整理FLASH里面的  初始化代码
	printf(" 当前显示模式是：%s\t%dx%d\r\n",((Para.SigMode == Mipi_Mode) ? "Mipi+SPI": ((Para.SigMode == CMD_Mode) ? "Command" : ((Para.SigMode == SPI3_Mode) ? "SPI3": "SPI4"))),Para.H_pixel,Para.V_pixel); 
	printf(" 像素时钟为 %.2fMHz \r\n",Para.pixel_clk);
    return Para;
}

void WorkStation(void)
{
	if(!GPIO_ReadInputDataBit(KEY4Periph_GPIO,KEY4))	//开机的时候，有某个按键按下的话，则进入Debug模式
	{
		Working_Mode = Debug_Mode;
		if(!GPIO_ReadInputDataBit(KEYPeriph_GPIO,KEY1)) 			//UP按键
        {
            if(!GPIO_ReadInputDataBit(KEY3Periph_GPIO,KEY3))       // DOWN按键
                NAND_EraseChip();
        }
        
        Device_ID_Buf[0] = 0;
        Device_Addr = Device_Flash_Addr;
        do
        {
            Device_ID = Device_ID_Buf[0];
            FLASH_If_Read(&Device_Addr, Device_ID_Buf, 0,1);	//将FLASH的模组Timing数据读取出来，准备发送给FPGA
        }
        while(Device_ID_Buf[0] != 0xFFFFFFFF);
        if((Device_ID == 0)||(Device_ID > 20))
            Device_ID = 1;
        Device_Addr -= 4;
        FPGA_RESET_LOW;			//FPGA复位
        LED_HIGH;
        USBD_Init(  &USB_OTG_dev,         //初始化USB 
                    USB_OTG_HS_CORE_ID,
                    &USR_desc, 
                    &USBD_CDC_cb, 
                    &USR_cb); 
	}
	else
	{
        if((Nand_FS_Init(Nand_Path) == fsOK))
        {
        	if(f_mount(&SD_fatfs,SD_Path,1) == FR_OK)
        	{
                disk = All_Disc;
                printf(" SD卡设备已插入\r\n");
        	}
			else disk = Nand_Disc;
        }
  
        if(disk == All_Disc)
            Updata_cfg_printf(Updata_cfg,SD_Conf_File,WriteAddress);        
        
        scan_files(disk,1);	//枚举存储器里所有的BMP图片，将磁盘里的BMP图片的名称全部拷贝到数组里面成功

        WriteAddress = Inter_Flash_Addr;
        FLASH_If_Read(&WriteAddress, buffer1, 0,4096);	//将FLASH的模组Timing数据读取出来，准备发送给FPGA
				OLED = OLED_Para_Process(buffer1);
        Loaded_BMPNum=BMP_Name_Process(disk,OLED.H_pixel,OLED.V_pixel);	//BMP图片分辨率 归类

        if(Loaded_BMPNum == 0)      //里面没有合适的图片就 只显示RGB WB
        {
            Loaded_BMPNum = sizeof Pure_Color_Table/sizeof Pure_Color_Table[0];
            Pure_Color_Flag = 1;   
        }
        else Pure_Color_Flag = 0;

        if(disk == All_Disc) 
        {

            LED_Flick = LED_Flick_Fast;           
            TIM_Cmd(TIM3,ENABLE); //使能定时器3	
            Delay_time = 0;
            if(BMP_Copy2_Nand())
                NVIC_SystemReset();
            TIM_Cmd(TIM3,DISABLE); //使能定时器3
        }

        if((OLED.SigMode == Mipi_Mode)||(OLED.SigMode == CMD_Mode))
        {	
            
            Load_done_LOW;           
            ICS307_Valid_Data = calculate_idt307_config(OLED.pixel_clk);	
            ICS307_ValidClk_Set(ICS307_Valid_Data);          
            FPGA_ResetProcess();
            FSMC_OLED_Parameter(buffer1,OLED.SigMode);

        }
    }
}


int main(void)
{   
    u8  First_Conf = 0;
    u32 VCP_Receive_BIN_True_num = 0;
	HardWare_Init();      	
    WorkStation();
    Set_2828_reset(OLED.SigMode);       //复位2828和OLED模组
	//DemuraAddHL=0xf00-256;	
    while (1)
    {    
        if(Working_Mode == Debug_Mode)
        {    
            if(USB_ReceivedCount>0)
            {      
                 
                if(SendTo_PC_cfgFile)           //返回配置文件到PCsw标志
                {
                    SendTo_PC_cfgFile=0;
                    USB_StatusDataSended=0;
                    WriteAddress = Inter_Flash_Addr;
                    Generate_cfg(&USB_OTG_dev,WriteAddress);
                    while(USB_StatusDataSended == 0)
                    {
                      delay_us(1);
                    }          
                } 
                else if(Receive_BIN_Flag1)
                {
                    Receive_BIN_Flag1 = 0;
                    Receive_BIN_Flag = 1;
                    VCP_Receive_BIN_True_num = 0;
                    Nand_FS_Init(Nand_Path);


                    fout = fopen ("N0:F4Updata.bin","w");       //创建STM32底层代码更新文件
                }
                else if((NUM==0)&&(Receive_BIN_Flag == 1))
                {

                    bw = fwrite (USB_Rx_Buffer,sizeof(uint8_t), USB_ReceivedCount, fout);  
                    
                    VCP_Receive_BIN_True_num+=USB_ReceivedCount;
                    if(VCP_Receive_BIN_True_num == Receive_BIN_Length)
                    {
                        VCP_Receive_BIN_True_num = 0;
                        USB_Rx_Buffer[0] = 0x55;
                        USB_Rx_Buffer[1] = 0x01;
                        USB_Rx_Buffer[3] = 0x01;
                        STM2PC_RM671xx(&USB_OTG_dev,CDC_IN_EP,USB_Rx_Buffer,USB_Rx_Buffer[2]+3);           //返回 写寄存器状态  ：ok
                        delay_ms(1);
                        Receive_BIN_Flag = 0;
                        
                        fclose(fout);
                        
                        fout = fopen ("N0:F4Updata_Bak.bin","w");       //创建STM32底层代码更新备份文件
                        WriteAddress = 0x8020000;

                        
                        for(i=0;i<32;i++)       //256KB的大小
                        {
                            FLASH_If_Read(&WriteAddress, buffer1, 0,2048);	//将FLASH的模组Timing数据读取出来，准备发送给FPGA
                            
                            for(j=0;j<2048;j++)
                            {
                                buffer[0] = (u8)buffer1[j];
                                buffer[1] = (u8)(buffer1[j]>>8);
                                buffer[2] = (u8)(buffer1[j]>>16);
                                buffer[3] = (u8)(buffer1[j]>>24);
                                bw = fwrite (buffer,sizeof(uint8_t), 4, fout);
                            }
                             
                        }
                        fclose(fout);                        
                        NVIC_SystemReset();

                    }
                    else if(VCP_Receive_BIN_True_num < Receive_BIN_Length)
                    {
                        USB_Rx_Buffer[0] = 0xFE;
                        USB_Rx_Buffer[1] = 0x01;
                        USB_Rx_Buffer[2] = 0x02;
                        
                        USB_Rx_Buffer[4] = Uart_Error_None;
                        STM2PC_RM671xx(&USB_OTG_dev,CDC_IN_EP,USB_Rx_Buffer,USB_Rx_Buffer[2]+3);           //返回 写寄存器状态  ：ok
                    }
                    else if(VCP_Receive_BIN_True_num > Receive_BIN_Length)
                    {
                        VCP_Receive_BIN_True_num = 0;
                        Receive_BIN_Flag = 0;
                        USB_Rx_Buffer[0] = 0x55;
                        USB_Rx_Buffer[1] = 0x01;
                        USB_Rx_Buffer[3] = 0x02;
                        STM2PC_RM671xx(&USB_OTG_dev,CDC_IN_EP,USB_Rx_Buffer,USB_Rx_Buffer[2]+3);           //返回 写寄存器状态  ：Error                       
                    }
                }
                USB_ReceivedCount=0;
            }
        }
        else
        {   
            if(First_Conf == 0)
            {
                First_Conf = 1;
								Panel_ON(OLED.SigMode,buffer1);
                Valid_BMP_No = 0;
                EXTIInit(); 
                EXIT_Enable(Enable);
                LED_Flick = LED_Flick_Slow;
                TIM_Cmd(TIM3,ENABLE); //使能定时器3 
                LED2_HIGH; 
                Key_Auto = 1;
            }

            if(Key_vaild)					//按键有效按下状态
            {    
                FSMC_Send_Flag = 0;
                Key_vaild = 0;
                Delay_time = 0;

                if(OLED.SigMode == Mipi_Mode)		//配置文件中信号格式 是Mipi信号
                {     
#if DSI_Set_Window_EN == 1                    
                    SSD2828_Set_Window(OLED.SigMode,CS1_2,(OLED.H_pixel==390) ? 4 : 0,(OLED.H_pixel==390) ? OLED.H_pixel+4 : OLED.H_pixel,0,OLED.V_pixel);
#endif                  
                    if(Pure_Color_Flag == 1)
                        FSMC_Pure_colour(Pure_Color_Table[Valid_BMP_No]);
                    else
												FSMC_Send_BMP(OLED.pixel_clk,DDR_Addr_ID,Valid_BMP_No);
                    Load_done_HIGH;			//图片载入完成                    
                }   
                else if(OLED.SigMode == CMD_Mode) 
                {   
#if DSI_Set_Window_EN == 1                    
                    SSD2828_Set_Window(OLED.SigMode,CS1_2,(OLED.H_pixel==390) ? 4 : 0,(OLED.H_pixel==390) ? OLED.H_pixel+4 : OLED.H_pixel,0,OLED.V_pixel);
#endif
                    if(Pure_Color_Flag == 1)
                        SSD2828_W_RAM_Pic(OLED.pixel_clk,OLED.SigMode,CS1_2,OLED.H_pixel,OLED.V_pixel,(Pure_Color_Table[Valid_BMP_No]&0xff0000)>>16,(Pure_Color_Table[Valid_BMP_No]&0x00ff00)>>8,Pure_Color_Table[Valid_BMP_No]&0x0000ff); 
                    else
                    {     
                        SSD2828_W_Reg(OLED.SigMode,CS1_2,0xBC,(u16)(OLED.H_pixel*OLED.V_pixel*3)); 
                        SSD2828_W_Reg(OLED.SigMode,CS1_2,0xBD,(u16)((OLED.H_pixel*OLED.V_pixel*3)>>16)); 
                        SSD2828_W_Reg(OLED.SigMode,CS1_2,0xBE,(u16)(OLED.H_pixel*3));                         
                        SSD2828_W_Cmd(OLED.SigMode,CS1_2,0xBF);
                        SSD2828_W_Cmd(OLED.SigMode,CS1_2,0X2C);                            
                        fout = fopen (valid_FileNames[Valid_BMP_No],"r");        //以只读的方式 打开 Nandflash 里的图片
                        for(i=0;i<OLED.V_pixel;i++)
                        {   
#if BMP_GROWTH == 1 
                            fseek (fout, ((OLED.V_pixel-1)-i)*(OLED.H_pixel*3+(OLED.H_pixel % 4))+54, SEEK_SET);
#else 
                            fseek (fout, i*(OLED.H_pixel*3+(OLED.H_pixel % 4))+54, SEEK_SET);            
#endif
                            br = fread(buffer,sizeof(uint8_t), OLED.H_pixel*3, fout);                          
                            SPI_CS_Select(CS1_2,0); 
                            SSD2828_W_RAM_buffer_8bits_part(OLED.pixel_clk,OLED.SigMode,buffer,OLED.H_pixel,1,0);
                            SPI_CS_Select(CS1_2,1);
                            
                        }
                        fclose(fout);  
                    }                        
                }
                else if((OLED.SigMode == SPI3_Mode)||(OLED.SigMode == SPI4_Mode))
                {
#if SPI_Set_Window_EN == 1                     
                    SPI_Set_Window(OLED.SigMode,CS1_2,0, OLED.H_pixel-1,0, OLED.V_pixel-1);
#endif                  
                    if(Pure_Color_Flag == 1)
                        SPI3_WriteRAM(OLED.SigMode,CS1_2,OLED.H_pixel,OLED.V_pixel,(Pure_Color_Table[Valid_BMP_No]&0xff0000)>>16,(Pure_Color_Table[Valid_BMP_No]&0x00ff00)>>8,Pure_Color_Table[Valid_BMP_No]&0x0000ff);
                    else
                    {
                        SPI_Write_code(OLED.SigMode,CS1_2 ,0xFE,0x01);
                        SPI_Write_code(OLED.SigMode,CS1_2 ,0x04,0x80);
                        SPI_Write_code(OLED.SigMode,CS1_2 ,0xFE,0x00);
                        SPI_Write_code(OLED.SigMode,CS1_2 ,0xC4,0x31);        // SP3T 2Wire

                        fout = fopen (valid_FileNames[Valid_BMP_No],"r");        //以只读的方式 打开 Nandflash 里的配置文件
                        fseek (fout, 54L, SEEK_SET);
                        for(j=0;j<OLED.V_pixel;j++)
                        {
#if BMP_GROWTH == 1
                            fseek (fout, ((OLED.V_pixel-1)-j)*(OLED.H_pixel*3)+54, SEEK_SET);
#endif
                            br = fread(buffer,sizeof(uint8_t), OLED.H_pixel*3, fout);
                            SPI_WriteRAM_buffer_part(OLED.SigMode,CS1_2,buffer,OLED.H_pixel,1,Rec_first_line_Flag);
                            if(Rec_first_line_Flag == 1)
                                Rec_first_line_Flag = 0;
                        }
                        fclose(fout);
                    }                        
                } 
                if(Pure_Color_Flag == 1)
                {
                    switch(Pure_Color_Table[Valid_BMP_No])
                    {
                        case RED:   printf(" 当前画面：红\r\n");break;
                        case GREEN: printf(" 当前画面：绿\r\n");break;
                        case BLUE:  printf(" 当前画面：蓝\r\n");break;
                        case WHITE: printf(" 当前画面：白\r\n");break;
                        case BLACK: printf(" 当前画面：黑\r\n");break;
                        case YELLOW:printf(" 当前画面：黄\r\n");break;
                        case PINK:  printf(" 当前画面：紫\r\n");break;
                        case CYAN:  printf(" 当前画面：青\r\n");break;
                    }
                }                       
                else
                    printf(" 当前画面:%s\t\t\t用时：%d\r\n",valid_FileNames[Valid_BMP_No],Delay_time);	

                Count_time = Delay_time;
                Delay_time = 0; 
                
                LED2_LOW;  
								EXIT_Enable(Enable);
                FSMC_Send_Flag = 1;                
            }				
        }
    }
}

u16 Load_flag=0;
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{

	if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET) //溢出中断
	{
		if(Key_Auto==1)
		{
            if(FSMC_Send_Flag == 1)
            {
                Count_time++;
                if(Count_time >= 1500)
                {
                    
                    LED2_HIGH;
                    Key_vaild = 1;
					EXIT_Enable(Disable);
                    if(Valid_BMP_No == (Loaded_BMPNum-1))		
                        Valid_BMP_No = 0;
                    else
                        Valid_BMP_No ++;

                    if(DDR_Addr_ID ==0)
                        DDR_Addr_ID = 1;
                    else
                        DDR_Addr_ID = 0;
                }
            }
		}
		Delay_time++;
		Load_flag++;
		if(Load_flag == LED_Flick)
			LED_HIGH;
		if(Load_flag == 2*LED_Flick)
		{
			LED_LOW;
			Load_flag = 0;
		}
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

void EXTI2_IRQHandler()
{	
    
	if(SET == EXTI_GetITStatus(EXTI_Line2))
	{	
		delay_ms(30);
		if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2))
		{
            if(Key_Auto == 0)
            {
                LED2_HIGH;
                Key_vaild = 1;
                EXIT_Enable(Disable);
                if(Valid_BMP_No == (Loaded_BMPNum-1))		
                    Valid_BMP_No = 0;
                else
                    Valid_BMP_No ++;
                if(DDR_Addr_ID ==0)
                    DDR_Addr_ID = 1;
                else
                    DDR_Addr_ID = 0;				
            }
		}
		EXTI_ClearITPendingBit(EXTI_Line2);	
		
	}
}

void EXTI9_5_IRQHandler()
{	
	if(SET==EXTI_GetITStatus(EXTI_Line8))
	{	
		delay_ms(30);
		if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_8))
		{
            if(Key_Auto == 0)
            {
                LED2_HIGH;
                Key_vaild = 1;
				EXIT_Enable(Disable);
                if(Valid_BMP_No == 0)
                    Valid_BMP_No = Loaded_BMPNum - 1;
                else
                    Valid_BMP_No --;
                if(DDR_Addr_ID ==0)
                    DDR_Addr_ID = 1;
                else
                    DDR_Addr_ID = 0;				
                
            }			
			

		}
		EXTI_ClearITPendingBit(EXTI_Line8);
		
	}
	else if(SET==EXTI_GetITStatus(EXTI_Line9))
	{	
		delay_ms(30);
		if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_9))
		{			
            if(Key_Auto == 0)
            {
                Key_Auto = 1;                
                Delay_time = 0;
            }
            else
            {
                Key_Auto = 0;
                Delay_time = 0;
            }			
			
		}
		EXTI_ClearITPendingBit(EXTI_Line9);		
	}	
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
